//
// Created by tang on 2022/5/15.
//

#ifndef DIARYTOOL_EDITOR_DATA_HPP
#define DIARYTOOL_EDITOR_DATA_HPP

#include "config.h"

#include <list>
#include <string>
#include "sql/types.hpp"

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif

// 树型结构的整理
/*
 * + 2021 (476项)
 * - 2022 (158项)
 *   + 1月 (66项)
 *   - 2月 (72项)
 *     + 2022/02/01 (3项)
 *     - 2022/02/02 (4项)
 *       ·摸鱼 1.5h
 *       ·摸鱼 3.5h
 *       ·摸鱼 1h
 *       ·摸鱼 2h
 *     + 2022/02/05 (4项)
 *     .
 *     .
 *     .
 *   + 3月 (30)
 *
 */

template<typename InnerType>
struct ExpandableNodeBase {
    using LoadDataFn = void (ExpandableNodeBase::*)();

    std::string child_key;
    std::string title;
    std::list<InnerType> children;
    bool loaded;
    LoadDataFn load_fn;

    template<typename T>
    explicit ExpandableNodeBase(std::string child_key, void (T::* f)()) :
        child_key(std::move(child_key)),
        loaded(false),
        load_fn(reinterpret_cast<LoadDataFn>(f)) {
    }

    void LoadInnerData() {
        if (loaded)
            return;
        loaded = true;
        if (load_fn) {
            (this->*load_fn)();
        }
    }
};

struct DIARY_APP_SDK_API ItemNode {
    WorkItem item;
    std::vector<Tag> item_tags;

    bool operator== (const ItemNode &) const { return false; }

    bool CanUpload() const;
};

struct DIARY_APP_SDK_API DayLevelNode : ExpandableNodeBase<ItemNode> {
    explicit DayLevelNode(std::string date);
    void LoadItems();

    bool operator== (const DayLevelNode&) const { return false; }
};

struct DIARY_APP_SDK_API MonthLevelNode : ExpandableNodeBase<DayLevelNode> {
    MonthLevelNode(std::string year, std::string month);

    void LoadDays();

    std::string year;
    std::string month;

    bool operator== (const MonthLevelNode&) const { return false; }
};

struct DIARY_APP_SDK_API YearLevelNode : ExpandableNodeBase<MonthLevelNode> {
    explicit YearLevelNode(std::string year);

    void LoadMonth();

    std::string year;

    bool operator== (const YearLevelNode&) const { return false; }
};

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif  // DIARYTOOL_EDITOR_DATA_HPP
